﻿using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace GUI
{
    public delegate void MountEventHandler(char letter, string password, string fileName);

    public partial class MainForm : Form
    {
        private AddControl addControl;

        private CreateNewForm createForm;

        private OpenExistingForm openForm;

        private bool canClose; //if true - close application. Else - hide form

        private string saveTilesFileName = Path.GetFullPath(Application.ExecutablePath) + "tiles.s";

        public MainForm()           //called in Program.cs
        // exception handlers for this constructor there are too
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CurrentCulture;
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentUICulture;

            InitializeComponent();

            try
            {
                addControl = new AddControl();
                addControl.MouseClick += addControl_Click;
                mainPanel.Controls.Add(addControl);
                canClose = false;
                notifyIcon.ContextMenuStrip = notifyIconContextMenu;
                using (FileStream fs = new FileStream(saveTilesFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    while (fs.CanRead)
                    {
                        DriveManagement.DriveInfo item = (DriveManagement.DriveInfo)bf.Deserialize(fs);
                        DriveManagement.DriveManager.AddDrive(item);
                        mainPanel.Controls.Add(new DriveInfoControl(item.Letter, item.FileName));
                    }
                }
            }
            catch (Exception)        // file with tiles is not accessible
            { }                      //just load empty form in exception case
        }

        private void addControl_Click(object sender, EventArgs e)
        {
            try
            {
                contexMenu.Show(addControl, (e as MouseEventArgs).X, (e as MouseEventArgs).Y);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fantastic error occured when trying to call contex menu. Original exception: " + ex.Message, "Unknown Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void openExistingToolStripMenuItem_Click_1(object sender, EventArgs e)
        {//only show dialog. Mounting will be processed on OK-Button-event
            try
            {
                if (openForm == null || openForm.IsDisposed)
                {
                    openForm = new OpenExistingForm();
                    openForm.MountEvent += Mount;
                }
                openForm.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can`t open dialog. Original exception: " + ex.Message, "Unknown Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void createNewToolStripMenuItem_Click(object sender, EventArgs e)
        {//only show dialog. Mounting will be processed on OK-Button-event
            try
            {
                if (createForm == null || createForm.IsDisposed)
                {
                    createForm = new CreateNewForm();
                    createForm.MountEvent += Mount;
                }
                createForm.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can`t open dialog. Original exception: " + ex.Message, "Unknown Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Mount(char letter, string password, string fileName)
        {
            try
            {
                System.IO.FileInfo f = new System.IO.FileInfo(fileName);
                var control = new DriveInfoControl(letter, fileName, password, f.Length);
                mainPanel.Controls.Add(control);
            }
            catch (ArgumentException ex)
            {               //be on a safe side
                MessageBox.Show(ex.Message, GUI.Resources.Strings.CheckParams);
            }
            catch (WinAPI.MarshalException ex)
            {//be on a safe side:)
                MessageBox.Show(GUI.Resources.Strings.SysErr + ex.Message, GUI.Resources.Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (DriveManagement.DriveManager.LetterIsBusyException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, GUI.Resources.Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void unmountAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(GUI.Resources.Strings.UmntAllText, GUI.Resources.Strings.UmntAll, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                foreach (Control item in mainPanel.Controls)
                {
                    if (item is DriveInfoControl)
                        (item as DriveInfoControl).Unmount();
                }
            }
        }
        #region form behavior logic

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(GUI.Resources.Strings.CloseText, GUI.Resources.Strings.Close, MessageBoxButtons.YesNo) == DialogResult.Yes)
                canClose = true;
            Close();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            //needs to hide window to notify
            //only user can`t close application
            if (e.CloseReason == CloseReason.UserClosing && canClose == false)
            {
                e.Cancel = true;
                WindowState = FormWindowState.Minimized;
                notifyIcon.Visible = true;
            }
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            //window is really closed, unmount all drives
            //exception handles in Program.cs
            using (FileStream fs = new FileStream(saveTilesFileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
            {
                BinaryFormatter bf = new BinaryFormatter();//for serialization
                foreach (Control item in mainPanel.Controls)
                {
                    if (item is DriveInfoControl)
                    {
                        (item as DriveInfoControl).Unmount();
                        bf.Serialize(fs, (item as DriveInfoControl).Info);
                    }
                }
            }
        }

        private void MainForm_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible == false)
            {
                notifyIcon.ShowBalloonTip(500, GUI.Resources.Strings.Minimized, GUI.Resources.Strings.MinimizedText, ToolTipIcon.Warning);
            }
        }

        private void MainForm_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                notifyIcon.Visible = true;
                Hide();
            }
        }

        private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
        {
            switch (e.Button)
            {
                case System.Windows.Forms.MouseButtons.Left:
                    Show();
                    WindowState = FormWindowState.Normal;
                    notifyIcon.Visible = false;
                    break;
                case System.Windows.Forms.MouseButtons.Right:
                    notifyIcon.ContextMenuStrip.Show(Cursor.Position);
                    break;
            }
        }
        #endregion
    }
}
